package pathways;

/**
 * Title:        Pathways
 * Description:  Pure Java version of the Pathways Project.
 * Copyright:    Copyright (c) 2002
 * Company:      Ants Technologies
 * @author Veejay Sani
 * @version 1.0
 */

import java.sql.ResultSet;
import java.util.Vector;

import pathways.Database.Implementation.CDatabase;
import pathways.util.Debug.CDebug;

public class CSpannerDataGatherer extends Thread
{
  private CDatabase db;
  private int mSubID;
  private volatile Vector mLevels;
  private int mMaxLevel;
  private int mProdID;
  private volatile boolean done = false;
  private volatile boolean mbSuspend = false;
  private volatile boolean mbStop = false;
  
  class dataWrapper
  {
    public int prodID;
    public int rxnID; 
  }  
  
  public CSpannerDataGatherer(CDatabase database, int subID, 
                           int maxLevel, int prodID)
  {
    db = database;
    mSubID = subID;
    mMaxLevel = maxLevel;
    mProdID = prodID;
    mLevels = new Vector();
    
    for (int i = 0; i < mMaxLevel+1; i++)
    {
      Vector v = new Vector();
      mLevels.add(v); 
    }
  }
  
  public Vector getLevels()
  {
    return mLevels;  
  }
  
  public boolean isFinished()
  {
    return done;    
  }
  
  public void doStuff()
  {
    getPathways(mSubID,mLevels,mMaxLevel,mProdID,0,mSubID);
  }
  
  public void run()
  {
    getPathways(mSubID,mLevels,mMaxLevel,mProdID,0,mSubID);
    mbStop = true;
  }
  
  public boolean isSuspended()
  {
    return mbSuspend; 
  }
  
  public void setSuspend(boolean suspend)
  {
    mbSuspend = suspend;  
  }

  public boolean isStopped()
  {
    return mbStop;  
  }
  
  public void setStop(boolean stop)
  {
    mbStop = stop;  
  }
    
  private void getPathways(int subID, Vector levels, int maxLevel, 
                           int prodID, int currentLevel, int initialSubID)
  {
    if (mbStop)
    {
       done = true;
       return;
    }
    
    if (mbSuspend)
    {
      try {
       //javax.swing.JOptionPane.showMessageDialog(null,"Now executing wait");
       synchronized (this) {
          while(mbSuspend)
            wait();
       }
          
      } catch (Exception excep) {
        //javax.swing.JOptionPane.showMessageDialog(null,"out of wait");
      }
    }
    
    if (currentLevel >= maxLevel) return;
    
    Vector currentLevelVector = (Vector)levels.get(currentLevel);
    int nextLevel = currentLevel + 1;
    Vector nextLevelVector = (Vector)levels.get(nextLevel); 
    
    // fetch records for the substrate
    Vector data = getData(subID);
    
    try {
      
      for (int i = 0; i<data.size() && mbStop == false;i++)
      {
        dataWrapper d = (dataWrapper)data.get(i);
        
        int dbProdID = d.prodID;
        
        if (dbProdID == prodID)
        {
          // add reaction id to current level
          currentLevelVector.add(new Integer(d.rxnID));
          for (i = currentLevel+1; i < maxLevel; i++)
          {
            Vector level = (Vector)levels.get(i);
            level.add(new Integer(0)); 
          }        
        }
        else if (isReactionALoop(d.rxnID,initialSubID))
        {
          // we don't consider loops to the substrate
          // so we ignore them 
        } 
        else
        {
          int lnextLevelCount = nextLevelVector.size();
           
          getPathways(dbProdID,levels,maxLevel,prodID,nextLevel,initialSubID);
          
          int diffInSize = nextLevelVector.size() - lnextLevelCount;
           
          for (int j = 0; j<diffInSize; j++)
          {
            // put the rxnID in the currentLevelVector
            currentLevelVector.add(new Integer(d.rxnID));
          } 
        } 
      }
      
    } catch (Exception e) {
      CDebug.println(this,"getPathways() Exception: " + e.toString());     
    }
    
    if (currentLevel == 0)
    {
      /*try {
          Thread.sleep(20);
      } catch(Exception e){}*/
    
      done = true;
   }
  }
  
  private boolean isReactionALoop(int rxnID, int initialSubID)
  {
    return db.getSelect().isProdOfReaction(rxnID,initialSubID);
  }
  
  private Vector getData(int subID)
  {
    Vector v = null;
    
    try {
    ResultSet rs = db.getSelect().getReactionsBySubstrate(subID);
    
    v = getVector(rs);
    
    rs.close();
    } catch (Exception e) {}
    
    return v;
  }
  
  private Vector getVector(ResultSet rs)
  {
    int prodID = 0;
    int rxnID = 0;
    Vector v = new Vector();
    
    try {
        while (rs.next())
        {
          prodID = rs.getInt(2);
          rxnID = rs.getInt(1);
          dataWrapper d = new dataWrapper();
          d.prodID = prodID;
          d.rxnID = rxnID;
          
          v.add(d);             
        }
    } catch (Exception e) {}
    
    return v; 
  }
}